home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 1999 November / Macworld (1999-11).dmg / Updaters / WhiteCap 3.0.4 / WhiteCap Source.sit / WhiteCap Source / Common / General Tools / UtilStr.cpp < prev    next >
Text File  |  1999-07-13  |  18KB  |  1,180 lines

  1.  
  2. #include "UtilStr.h"
  3.  
  4.  
  5. #include "CEgIStream.h"
  6. #include "CEgOStream.h"
  7.  
  8.  
  9. #ifdef EG_WIN
  10. #ifndef HBITMAP
  11. #include <windows.h>
  12. #endif
  13. #else
  14. #include <OSUtils.h>
  15. #endif
  16.  
  17. UtilStr::UtilStr() {
  18.  
  19.     init();
  20. }
  21.  
  22.  
  23.  
  24. UtilStr::UtilStr( const char* inCStr ) {
  25.     init();
  26.     Append( inCStr );
  27. }
  28.  
  29.  
  30.  
  31.  
  32. UtilStr::UtilStr( const unsigned char* inStrPtr ) {
  33.     init();
  34.     Append( inStrPtr );
  35. }
  36.  
  37.  
  38.  
  39. UtilStr::UtilStr( const UtilStr& inStr ) {
  40.     init();
  41.     Append( &inStr );
  42. }
  43.  
  44.  
  45.  
  46. UtilStr::UtilStr( const UtilStr* inStr ) {
  47.     init();
  48.  
  49.     Append( inStr );
  50. }
  51.  
  52.  
  53.  
  54. UtilStr::UtilStr( long inNum ) {
  55.     init();
  56.     Append( inNum );
  57. }
  58.  
  59.  
  60. UtilStr::UtilStr( const void* inPtr, long bytes ) {
  61.  
  62.     init();
  63.     Append( inPtr, bytes );
  64. }
  65.  
  66.  
  67.  
  68.  
  69.  
  70. UtilStr::~UtilStr() {
  71.  
  72.     if ( mBuf ) 
  73.         delete mBuf;
  74. }
  75.  
  76.  
  77.  
  78. void UtilStr::init() {
  79.  
  80.     mStrLen            = 0;
  81.     mBufSize         = 0;
  82.     mBuf            = NULL;
  83. }
  84.  
  85.  
  86.  
  87. void UtilStr::Swap( UtilStr& ioStr ) {
  88.     long len = mStrLen, size = mBufSize;
  89.     char* buf = mBuf;
  90.     
  91.     mBuf            = ioStr.mBuf;
  92.     mStrLen            = ioStr.mStrLen;
  93.     mBufSize        = ioStr.mBufSize;
  94.     
  95.     ioStr.mBuf        = buf;
  96.     ioStr.mStrLen    = len;
  97.     ioStr.mBufSize    = size;
  98. }
  99.  
  100.  
  101.  
  102. unsigned char* UtilStr::getPasStr() const {
  103.     
  104.     if ( ! mBuf )
  105.         return (unsigned char*) "\0";
  106.         
  107.     if ( mStrLen < 255 )
  108.         mBuf[0] = mStrLen;
  109.     else
  110.         mBuf[0] = 255;
  111.  
  112.     return (unsigned char*) &mBuf[0];
  113. }
  114.  
  115.  
  116.  
  117.  
  118. char* UtilStr::getCStr() const {
  119.  
  120.     if ( mBuf ) {
  121.         mBuf[ mStrLen + 1 ] = '\0';
  122.         return &mBuf[1]; }
  123.     else
  124.         return "\0";
  125.  
  126. }
  127.  
  128.  
  129.  
  130.  
  131.  
  132.  
  133.  
  134. void UtilStr::Append( const  char* inCStr ) {
  135.     register unsigned long i = 0;
  136.  
  137.     if ( inCStr ) {
  138.         while( inCStr[ i ] != '\0' ) 
  139.             i++;
  140.         Append( inCStr, i );
  141.     }
  142. }
  143.  
  144.  
  145.  
  146. void UtilStr::Append( const unsigned char* inStrPtr ) {
  147.     
  148.     if ( inStrPtr ) 
  149.         Append( (char*) &inStrPtr[1], inStrPtr[0] );
  150.     
  151. }
  152.         
  153.         
  154.  
  155. void UtilStr::Append( const void* inSrce, long numBytes ) {
  156.     unsigned long newLen = numBytes + mStrLen;
  157.     char* oldBuf;
  158.         
  159.     if ( numBytes > 0 ) {
  160.         if ( newLen >= mBufSize ) {
  161.             if ( newLen < 80 )
  162.                 mBufSize = newLen + 5;
  163.             else if ( newLen < 500 )
  164.                 mBufSize = newLen + 100;
  165.             else mBufSize = newLen + 3000;
  166.                 
  167.             oldBuf = mBuf;
  168.             mBuf = new char[ mBufSize + 2 ];    // One for pascal byte, one for c NUL byte
  169.             if ( oldBuf ) {
  170.                 if ( mStrLen > 0 )
  171.                     Move( &mBuf[1], &oldBuf[1], mStrLen );
  172.             
  173.                 delete oldBuf;
  174.             }
  175.         }
  176.                 
  177.         if ( inSrce && numBytes > 0 )
  178.             Move( &mBuf[mStrLen + 1], inSrce, numBytes );
  179.                 
  180.         mStrLen = newLen;
  181.     }
  182. }
  183.  
  184.  
  185.  
  186.  
  187.  
  188. void UtilStr::Append( long inNum ) {
  189.     UtilStr temp;
  190.     unsigned long i;
  191.  
  192.     if ( inNum < 0 ) {
  193.         Append( '-' );
  194.         inNum = - inNum;
  195.     }
  196.         
  197.     if ( inNum == 0 )
  198.         Append( '0' );
  199.         
  200.     while ( inNum > 0 ) {
  201.         temp.Append( (char) ('0' + inNum % 10) );
  202.         inNum = inNum / 10;
  203.     }
  204.     
  205.     for ( i = temp.length(); i > 0; i-- ) 
  206.         Append( temp.getChar( i ) );
  207. }
  208.  
  209.  
  210.  
  211.  
  212.  
  213.  
  214.  
  215. void UtilStr::Append( const UtilStr* inStr ) { 
  216.  
  217.     if ( inStr )
  218.         Append( inStr -> getCStr(), inStr -> length() );
  219. }
  220.  
  221.  
  222.  
  223.  
  224.  
  225.  
  226. void UtilStr::Assign( const UtilStr& inStr ) {
  227.  
  228.     if ( this != &inStr ) {
  229.         Wipe();
  230.         Append( inStr.getCStr(), inStr.length() );
  231.     }
  232. }
  233.  
  234.  
  235.  
  236. void UtilStr::Assign( const void* inPtr, long bytes ) {
  237.     Wipe();
  238.     Append( inPtr, bytes );
  239. }
  240.  
  241.  
  242.  
  243. void UtilStr::Assign( char inChar ) {
  244.     Wipe();
  245.     Append( &inChar, 1 );
  246. }
  247.  
  248.  
  249.         
  250. void UtilStr::Assign( long inNum ) {
  251.     
  252.     Wipe();
  253.     Append( inNum );
  254. }
  255.  
  256.  
  257.  
  258.         
  259.  
  260.  
  261.  
  262.  
  263. void UtilStr::Assign( const unsigned char* inStrPtr ) {
  264.     Wipe();
  265.     Append( inStrPtr );
  266. }
  267.  
  268.  
  269.  
  270.  
  271.  
  272. void UtilStr::Assign( const UtilStr* inStr ) {
  273.     
  274.     
  275.     if ( inStr != this ) {
  276.         Wipe();
  277.         if ( inStr )
  278.             Append( inStr -> getCStr(), inStr -> length() );
  279.     }
  280. }
  281.  
  282.  
  283.  
  284. void UtilStr::Assign( CEgIStream& inStream, long numBytes ) {
  285.  
  286.     if ( numBytes > 5000000 )                        // *** Safe to say that sizes over this are corrupt?
  287.         inStream.throwErr( cCorrupted );
  288.     else if ( numBytes > 0 ) {
  289.         Dim( numBytes );
  290.         if ( length() < numBytes )
  291.             numBytes = length();
  292.         inStream.GetBlock( getCStr(), numBytes );
  293.     }
  294. }
  295.  
  296.     
  297.  
  298.  
  299.  
  300.  
  301. void UtilStr::ReadFrom( CEgIStream* inStream ) {
  302.     unsigned long len = inStream -> GetLong();        // Grab the length
  303.  
  304.     Assign( *inStream, len );
  305. }
  306.  
  307.  
  308.  
  309.  
  310. void UtilStr::WriteTo( CEgOStream* inStream ) const {
  311.  
  312.     inStream -> PutLong( length() );
  313.     inStream -> PutBlock( getCStr(), length() );
  314. }
  315.  
  316.  
  317.  
  318.  
  319.  
  320.  
  321. void UtilStr::Prepend( char inChar ) {
  322.     
  323.     Insert( 0, &inChar, 1 );
  324. }
  325.  
  326.  
  327. void UtilStr::Prepend( UtilStr& inStr ) {
  328.  
  329.     Insert( 0, inStr.getCStr(), inStr.length() );
  330. }
  331.  
  332.  
  333.  
  334. void UtilStr::Prepend( const char* inStr ) {
  335.     long len = 0;
  336.     
  337.     while ( *(char*)(inStr + len) != 0 )
  338.         len++;
  339.     
  340.     Insert( 0, inStr, len );
  341. }
  342.  
  343.     
  344. void UtilStr::Insert( unsigned long inPos, char inChar, long inNumTimes ) {
  345.     unsigned long    oldLen = length();
  346.     unsigned long    numAddable;
  347.     
  348.     if ( inPos > oldLen )
  349.         inPos = oldLen;
  350.     
  351.     Insert( inPos, (char*) NULL, inNumTimes );
  352.     numAddable = length() - oldLen;
  353.     if ( numAddable > 0 && mBuf ) {
  354.         while ( inNumTimes > 0 ) {
  355.             mBuf[ inPos + inNumTimes ] = inChar;
  356.             inNumTimes--;
  357.         }
  358.     }
  359. }
  360.  
  361.  
  362. void UtilStr::Insert( unsigned long inPos, long inNum ) {
  363.     UtilStr numStr( inNum );
  364.     
  365.     Insert( inPos, numStr );
  366.     
  367. }
  368.  
  369. void UtilStr::Insert( unsigned long inPos, const UtilStr& inStr ) {
  370.     Insert( inPos, inStr.getCStr(), inStr.length() );
  371. }
  372.  
  373.      
  374. void UtilStr::Insert( unsigned long inPos, const char* inSrce, long inBytes ) {
  375.     unsigned long numToMove, len = length();
  376.     
  377.     if ( inPos >= len )
  378.         Append( inSrce, inBytes );
  379.     else if ( inBytes > 0 ) {
  380.         Append( NULL, inBytes );
  381.         numToMove = len - inPos;
  382.         if ( numToMove > 0 )
  383.             Move( &mBuf[ inPos + inBytes + 1 ], &mBuf[ inPos + 1 ], numToMove );
  384.         if ( inBytes > 0 && inSrce )
  385.             Move( &mBuf[ inPos + 1 ], inSrce, inBytes );
  386.     }
  387. }
  388.  
  389.  
  390.  
  391.  
  392.  
  393.  
  394.  
  395. void UtilStr::Move( void* inDest, const void* inSrce, unsigned long inNumBytes ) {
  396.  
  397.     if ( inNumBytes <= 64 ) {
  398.         register unsigned char* dest = (unsigned char*) inDest;
  399.         register unsigned char* srce = (unsigned char*) inSrce;
  400.         if ( srce > dest )
  401.             while ( inNumBytes > 0 ) {
  402.                 *dest = *srce;
  403.                 dest++;
  404.                 srce++;
  405.                 inNumBytes--;
  406.             }
  407.         else {
  408.             dest += inNumBytes;
  409.             srce += inNumBytes;
  410.             while ( inNumBytes > 0 ) {
  411.                 dest--;
  412.                 srce--;
  413.                 *dest = *srce;
  414.                 inNumBytes--;
  415.             } } }
  416.     else
  417.         #ifdef EG_WIN
  418.         ::MoveMemory( inDest, inSrce, inNumBytes );
  419.         #elif EG_MAC
  420.         ::BlockMove( inSrce, inDest, inNumBytes );
  421.         #else
  422.         You must have EG_MAC or EG_WIN and EG_WIN32 defined as 1 to compile Common!
  423.         #endif
  424. }
  425.  
  426.  
  427.         
  428. void UtilStr::Decapitalize() {
  429.     unsigned long i, len = length();
  430.     unsigned char c, sp;
  431.     
  432.     for( i = 2; i <= len; i++ ) {
  433.         c =     getChar( i );
  434.         sp =     getChar( i-1 );
  435.         if ( ( sp >= 'A' && sp <= 'Z' ) || ( sp >= 'a' && sp <= 'z' ) )  {
  436.             if ( getChar( i-1 ) == 'I' && c == 'I' ) { }    // Prevent III from decapitalizing
  437.             else if ( c >= 'A' && c <= 'Z' )
  438.                 setChar( i, c + 32 );
  439.         }
  440.     }
  441.  
  442. }
  443.  
  444.  
  445.  
  446.  
  447.  
  448. void UtilStr::Capitalize() {
  449.     unsigned long i, len = length();
  450.     char c;
  451.     
  452.     for( i = 1; i <= len; i++ ) {
  453.         c = getChar( i );
  454.         if ( c >= 'a' && c <= 'z' )  {
  455.             setChar( i, c - 32 );
  456.         }
  457.     }
  458.  
  459. }
  460.  
  461.  
  462.  
  463.  
  464. void UtilStr::Trunc( unsigned long numToChop, bool fromRight ) {
  465.     
  466.     if ( fromRight )
  467.         Remove( length() - numToChop + 1, numToChop );
  468.     else
  469.         Remove( 1, numToChop );
  470. }
  471.  
  472.  
  473.  
  474.  
  475. void UtilStr::Remove( unsigned long inPos, unsigned long inNum ) {
  476.     unsigned long    toMove;
  477.     unsigned long    len        = length();
  478.  
  479.     if ( inPos < 1 )
  480.         inPos = 1;
  481.     
  482.     if ( inNum > len - inPos + 1 )
  483.         inNum = len - inPos + 1;
  484.     
  485.     if ( inPos <= len && inNum > 0 ) {
  486.  
  487.         mStrLen = len - inNum;
  488.         toMove = len - inPos - inNum + 1;
  489.  
  490.         if ( toMove > 0 )
  491.             Move( &mBuf[ inPos ], &mBuf[ inPos + inNum ], toMove );
  492.     }    
  493. }
  494.  
  495.  
  496.  
  497.  
  498. void UtilStr::Remove( char* inStr, int inLen, bool inCaseSensitive ) {
  499.     long pos;
  500.     char* s;
  501.     
  502.     if ( inLen < 0 ) {
  503.         inLen = 0;
  504.         s = inStr;
  505.         while ( *s ) {
  506.             inLen++;
  507.             s++;
  508.         }
  509.     }
  510.     
  511.     pos = contains( inStr, inLen, 0, inCaseSensitive );
  512.     while ( pos > 0 ) {
  513.         Remove( pos, inLen );
  514.         pos--;
  515.         pos = contains( inStr, inLen, pos, inCaseSensitive );
  516.     } 
  517. }
  518.  
  519.  
  520.  
  521.  
  522.  
  523. void UtilStr::Keep( unsigned long inNumToKeep ) {
  524.  
  525.     if ( inNumToKeep < length() )
  526.         Trunc( length() - inNumToKeep, true );
  527. }
  528.  
  529.  
  530.  
  531.  
  532. void UtilStr::PoliteKeep( unsigned long inMaxLen, unsigned long inPos ) {
  533.     if ( length() > inMaxLen ) {
  534.         Remove( inPos + 1, length() - inMaxLen + 1 );
  535.         setChar( inPos, '…' );
  536.     }
  537. }
  538.  
  539.  
  540.  
  541. void UtilStr::ZapLeadingSpaces() {
  542.     unsigned long     i         = 1;
  543.     unsigned long    len        = length();
  544.  
  545.     while ( getChar( i ) == ' ' && i <= len )
  546.         i++;
  547.         
  548.     if ( i > 1 )
  549.         Trunc( i - 1, false );
  550. }
  551.  
  552.  
  553.  
  554.  
  555.  
  556. /*
  557.  
  558.  
  559. UtilStr UtilStr::MID( unsigned long start, unsigned long inLen ) const {
  560.     UtilStr        newStr;
  561.     unsigned long    len = length();
  562.     
  563.     if ( start < 1 )
  564.         start = 1;
  565.     
  566.     start--;
  567.         
  568.     if ( inLen > len - start ) 
  569.         inLen = len - start;    
  570.         
  571.     if ( start <= len && inLen > 0 ) 
  572.         newStr.Assign( getCStr() + start, inLen );
  573.         
  574.     return newStr;
  575. }
  576.  
  577.  
  578.  
  579.  
  580. UtilStr UtilStr::RIGHT( unsigned long inLen ) const {
  581.     UtilStr        newStr;
  582.     unsigned long     start, len = length();
  583.     
  584.     if ( inLen > len )
  585.         inLen = len;
  586.         
  587.     start = len - inLen;
  588.  
  589.     newStr.Assign( getCStr() + start, inLen );
  590.     return newStr;
  591. }
  592. */
  593.  
  594.  
  595.  
  596.  
  597.  
  598.  
  599.  
  600. long UtilStr::FindNextInstanceOf( long inPos, char c ) const {
  601.     long len = length(), i;
  602.     
  603.     if ( inPos < 0 )
  604.         inPos = 0;
  605.         
  606.     for ( i = inPos+1; i <= len; i++ ) {
  607.         if ( mBuf[ i ] == c )
  608.             return i;
  609.     }
  610.     
  611.     return 0;
  612. }
  613.  
  614.  
  615. long UtilStr::FindPrevInstanceOf( long inPos, char c ) const {
  616.     long i;
  617.     
  618.     if ( inPos > length() )
  619.         inPos = length();
  620.     
  621.     for ( i = inPos; i > 0; i-- ) {
  622.         if ( mBuf[ i ] == c )
  623.             return i;
  624.     }
  625.     
  626.     return 0;
  627. }
  628.  
  629.  
  630. void UtilStr::Replace( char inTarget, char inReplacement ) {
  631.     unsigned long i, len = length();
  632.     
  633.     for ( i = 1; i <= len; i++ )
  634.         if ( mBuf[ i ] == inTarget )
  635.             mBuf[ i ] = inReplacement;
  636. }
  637.  
  638.  
  639.  
  640. void UtilStr::copyTo( unsigned char* pasDestPtr, unsigned char inBytesToCopy ) const {
  641.     unsigned long     bytes = length() + 1;
  642.  
  643.     if ( bytes > inBytesToCopy ) 
  644.         bytes = inBytesToCopy;
  645.         
  646.     getPasStr();            // refreshes len byte for pas str 
  647.     
  648.     if ( bytes > 255 )
  649.         bytes = 255;
  650.  
  651.     Move( pasDestPtr, &mBuf[0], bytes );
  652. }
  653.  
  654.  
  655.  
  656.  
  657. void UtilStr::copyTo( char* inDestPtr, unsigned long inBytesToCopy ) const {
  658.     unsigned long bytes = length() + 1;
  659.  
  660.     if ( bytes > inBytesToCopy ) 
  661.         bytes = inBytesToCopy;
  662.         
  663.     getCStr();            // refreshes NUL byte for c strs
  664.  
  665.  
  666.     Move( inDestPtr, &mBuf[1], bytes );
  667. }
  668.  
  669.  
  670.  
  671.  
  672.  
  673.  
  674.  
  675. char UtilStr::getChar( unsigned long i ) const {
  676.  
  677.     if ( i <= mStrLen && i > 0 )
  678.         return mBuf[ i ];
  679.     else
  680.         return '\0'; 
  681. }
  682.  
  683.  
  684.  
  685. void UtilStr::setChar( unsigned long i, char inChar ) {
  686.  
  687.  
  688.     if ( i <= mStrLen && i > 0 ) 
  689.         mBuf[ i ] = inChar; 
  690. }
  691.  
  692.  
  693.  
  694.  
  695.  
  696. int UtilStr::StrCmp( const char* s1, const char* s2, long inN, bool inCaseSensitive ) {
  697.     char c1, c2;
  698.     
  699.     if ( inN < 0 ) {
  700.         inN = 0;
  701.         const char* s = (*s1 != 0) ? s1 : s2;
  702.         while ( *s ) {
  703.             s++;
  704.             inN++;
  705.         }
  706.     }
  707.         
  708.     while ( inN > 0 ) {
  709.         inN--;
  710.         c1 = *s1;
  711.         s1++;
  712.         c2 = *s2;
  713.         s2++;
  714.         if ( ! inCaseSensitive ) {
  715.             if ( c1 >= 'a' && c1 <= 'z' )
  716.                 c1 -= 32;
  717.             if ( c2 >= 'a' && c2 <= 'z' )
  718.                 c2 -= 32;    
  719.         }
  720.         if ( c1 != c2 )
  721.             return c1 - c2;
  722.     }
  723.     
  724.     return 0;    
  725. }
  726.  
  727.  
  728.  
  729.  
  730. int UtilStr::compareTo( const unsigned char* inPStr, bool inCaseSensitive ) const {
  731.     
  732.     if ( inPStr ) {
  733.         if ( length() == inPStr[0] ) {
  734.             return StrCmp( getCStr(), (char*) (inPStr + 1), length(), inCaseSensitive );
  735.         }
  736.     }
  737.  
  738.     return -1;
  739. }
  740.  
  741.  
  742. int UtilStr::compareTo( const UtilStr* inStr, bool inCaseSensitive ) const {
  743.  
  744.     if ( inStr )
  745.         return StrCmp( inStr -> getCStr(), getCStr(), length() + 1, inCaseSensitive );
  746.     else
  747.         return -1;
  748. }
  749.  
  750.  
  751. int UtilStr::compareTo( const char* inStr, bool inCaseSensitive ) const {
  752.     if ( inStr ) 
  753.         return StrCmp( inStr, getCStr(), length() + 1, inCaseSensitive );
  754.     else
  755.         return -1;
  756. }
  757.  
  758.  
  759.  
  760. long UtilStr::contains( const char* inSrchStr, int inLen, int inStartingPos, bool inCaseSensitive ) const {
  761.     char    srchChar, srchCharLC, c;
  762.     char*    endPtr, *curPtr = getCStr();
  763.  
  764.     if ( inLen < 0 ) {
  765.         inLen = 0;
  766.         while ( *(inSrchStr+inLen) )
  767.             inLen++;
  768.     }
  769.     
  770.     endPtr = curPtr + length() - inLen;
  771.     
  772.     srchChar = *inSrchStr;
  773.     if ( srchChar >= 'a' && srchChar <= 'z' )
  774.         srchChar -= 32;
  775.     srchCharLC    = srchChar + 32;
  776.     if ( inStartingPos > 0 )
  777.         curPtr += inStartingPos;
  778.     
  779.     while ( curPtr <= endPtr ) {
  780.         c = *curPtr;
  781.         if ( c == srchChar || c == srchCharLC ) {
  782.             if ( StrCmp( curPtr, inSrchStr, inLen, inCaseSensitive ) == 0 )
  783.                 return curPtr - getCStr() + 1;
  784.         }
  785.         curPtr++;
  786.     }
  787.     
  788.     return 0;
  789. }
  790.  
  791.  
  792. /*
  793. bool UtilStr::equalTo( const char* inStr, int inFlags ) const {
  794.     bool        stillOk             = inStr != NULL;
  795.     char*        thisStr             = getCStr();
  796.     char        c1 = 1, c2            = 2;
  797.     bool        caseInsensitive     = inFlags & cCaseInsensitive != 0;
  798.         
  799.     while ( stillOk && c2 != 0 ) {
  800.         c1 = *inStr;
  801.         c2 = *thisStr;
  802.         if ( caseInsensitive ) {
  803.             if ( c1 >= 'a' && c1 <= 'z' )
  804.                 c1 -= 32;
  805.             if ( c2 >= 'a' && c2 <= 'z' )
  806.                 c2 -= 32;    
  807.         }
  808.         stillOk = c1 == c2;
  809.         thisStr    += 1;
  810.         inStr    += 1;
  811.     }
  812.     
  813.     if ( ( inFlags & cLefthand ) && c2 == 0 )
  814.         stillOk = true;
  815.     
  816.     return stillOk;
  817. }
  818. */
  819.  
  820.  
  821.  
  822.  
  823.  
  824.  
  825.  
  826.  
  827.  
  828.  
  829.  
  830. long UtilStr::GetIntValue( char* inStr, long inLen, long* outPlacePtr ) {
  831.     bool seenNum = false;
  832.     char c;
  833.     long i, ret = 0, place = 1;
  834.     
  835.     for ( i = inLen - 1; i >= 0; i-- ) {
  836.         c = inStr[ i ];
  837.         if ( c >= '0' && c <= '9' ) {
  838.             seenNum = true;
  839.             ret += place * ( c - '0' );
  840.             place *= 10; }
  841.         else if ( seenNum )
  842.             i = 0;        // Stop loop
  843.     }
  844.     
  845.     if ( outPlacePtr )
  846.         *outPlacePtr = place;
  847.         
  848.     return ret;
  849. }
  850.  
  851.  
  852.  
  853.  
  854.  
  855. double UtilStr::GetFloatVal( char* inStr, long inLen ) {
  856.     unsigned long i, decLoc = 0, foundLet = false;
  857.     char c;
  858.     double n = 0, place = 1.0;
  859.     bool isNeg = false;
  860.     
  861.  
  862.     for ( i = 0; i < inLen; i++ ) {
  863.         c = inStr[ i ];
  864.         
  865.         if ( c == '-' && ! foundLet ) 
  866.             isNeg = true;
  867.             
  868.         if ( c >= '0' && c <= '9' ) {
  869.             n = 10.0 * n + ( c - '0' );
  870.             if ( decLoc )
  871.                 place *= 10.0;
  872.         }
  873.         
  874.         if ( c != ' ' )
  875.             foundLet = true;
  876.             
  877.         if ( c == '.' )
  878.             decLoc = i+1;
  879.     }
  880.     
  881.     if ( isNeg )
  882.         n = - n;
  883.  
  884.     return n / place;
  885. }
  886.  
  887.  
  888.  
  889.  
  890. double UtilStr::GetFloatValue() const {
  891.     return GetFloatVal( mBuf + 1, mStrLen );
  892. }
  893.  
  894.  
  895.  
  896.  
  897. long UtilStr::GetValue( long inMultiplier ) const {
  898.     unsigned long i, len = length(), decLoc = 0, foundLet = false;
  899.     char c;
  900.     long left, right, place;
  901.     
  902.     for ( i = 1; i <= len; i++ ) {
  903.         c = mBuf[ i ];
  904.         
  905.         if ( c == '-' && ! foundLet ) 
  906.             inMultiplier *= -1;
  907.         
  908.         if ( c != ' ' )
  909.             foundLet = true;
  910.             
  911.         if ( c == '.' )
  912.             decLoc = i;
  913.     }
  914.     
  915.     if ( ! decLoc )
  916.         decLoc = len + 1;
  917.         
  918.     left     = GetIntValue( mBuf + 1, decLoc - 1 );
  919.     right     = GetIntValue( mBuf + decLoc + 1, len - decLoc, &place );
  920.  
  921.     return ( inMultiplier * right + place / 2 ) / place + inMultiplier * left;
  922. }
  923.  
  924.  
  925.  
  926.  
  927. void UtilStr::SetValue( long inVal, long inDivisor, int inNumDecPlaces ) {    
  928.     long            i, part     = inVal % inDivisor;
  929.     UtilStr        partStr;
  930.     
  931.     for ( i = 0; i < inNumDecPlaces; i++ )
  932.         part *= 10;
  933.         
  934.     part /= inDivisor;
  935.     
  936.     i = inVal / inDivisor;
  937.     if ( i != 0 || part <= 0 )
  938.         Assign( i );
  939.     else
  940.         Wipe();
  941.     
  942.     if ( part > 0 ) {
  943.         Append( '.' );
  944.         partStr.Append( part );
  945.         
  946.         for ( i = inNumDecPlaces - partStr.length(); i > 0; i-- )
  947.             Append( '0' );
  948.             
  949.         Append( &partStr );
  950.         while ( getChar( length() ) == '0' )
  951.             Trunc( 1 ); 
  952.     }
  953.         
  954. }
  955.     
  956.  
  957.  
  958.  
  959.  
  960.  
  961.  
  962.  
  963.  
  964.  
  965.  
  966.  
  967.  
  968.  
  969.  
  970.  
  971.  
  972. void UtilStr::AppendAsMeta( const UtilStr* inStr ) {
  973.  
  974.     if ( inStr )
  975.         AppendAsMeta( inStr -> getCStr(), inStr -> length() );
  976. }
  977.  
  978.  
  979.  
  980.  
  981. void UtilStr::AppendAsMeta( const void* inPtr, long inLen ) {
  982.     const unsigned char* ptr = (unsigned char*) inPtr;
  983.     unsigned char c;
  984.     
  985.     Append( '"' );
  986.     
  987.     if ( ptr ) {
  988.         while ( inLen > 0 ) {
  989.             c = *ptr;
  990.             
  991.             if ( c == '"' )                         // Our flag was detected...
  992.                 Append( (char) '"' );                // Two flags in a row signal an actual "
  993.             
  994.             if ( c < 32 || c > 127 ) {
  995.                 Append( (char) '"' );
  996.                 Append( (long) c );
  997.                 Append( (char) '"' ); }
  998.             else 
  999.                 Append( &c, 1 );
  1000.             inLen--;
  1001.             ptr++;
  1002.         }
  1003.     }
  1004.     Append( '"' );
  1005. }
  1006.  
  1007.  
  1008.  
  1009.  
  1010. void UtilStr::AppendFromMeta( const void* inPtr, long inLen ) {
  1011.     const unsigned char* ptr = (unsigned char*) inPtr;
  1012.     unsigned char c;
  1013.     static UtilStr ascNum;
  1014.     
  1015.     if ( ptr ) {
  1016.         if ( *ptr != '"' )                            // First char should be a "
  1017.             return;
  1018.         inLen--;
  1019.         ptr++;
  1020.         
  1021.         while ( inLen > 1 ) {                        // We stop 1 char early cuz last char should be a "
  1022.             c = *ptr;
  1023.             
  1024.             if ( c == '"' ) {                        // If the flag is detected...
  1025.                 inLen--;
  1026.                 ptr++;
  1027.                 c = *ptr;
  1028.                 if ( inLen > 1 && c != '"' ) {        // Ignore double flags (they signify the flag char)
  1029.                     ascNum.Wipe();
  1030.                     while ( c >= '0' && c <= '9' ) {
  1031.                         ascNum.Append( (char) c );            
  1032.                         inLen--;
  1033.                         ptr++;
  1034.                         c = *ptr;
  1035.                     }
  1036.                     c = ascNum.GetValue();                        
  1037.                 } 
  1038.             }
  1039.             
  1040.             Append( (char) c );
  1041.  
  1042.             inLen--;
  1043.             ptr++;
  1044.         }
  1045.     }
  1046. }
  1047.  
  1048.  
  1049.  
  1050.  
  1051.  
  1052.  
  1053.  
  1054. UtilStr UtilStr::operator + ( const UtilStr& inStr ) {
  1055.     UtilStr    newStr( this );
  1056.     
  1057.     newStr.Append( &inStr );
  1058.     return newStr;
  1059. }
  1060.  
  1061.  
  1062.  
  1063. UtilStr UtilStr::operator + ( const char*  inCStr ) {
  1064.     UtilStr    newStr( this );
  1065.     
  1066.     newStr.Append( inCStr );
  1067.     return newStr;
  1068. }
  1069.  
  1070.  
  1071.  
  1072. UtilStr UtilStr::operator + ( long inNum ) {
  1073.     UtilStr    newStr( this );
  1074.     
  1075.     newStr.Append( inNum );
  1076.     return newStr;
  1077. }
  1078.  
  1079.  
  1080.  
  1081.  
  1082. UtilStr& UtilStr::operator = ( const UtilStr& inStr ) {
  1083.     Wipe();
  1084.     
  1085.     Append( inStr.getCStr() );
  1086.     return *this;
  1087. }
  1088.  
  1089.  
  1090.  
  1091.  
  1092.  
  1093.  
  1094.  
  1095. long UtilStr::Hash() const {
  1096.     long hash = 0;
  1097.     const char* stop    = getCStr();
  1098.     const char* curPos    = stop + mStrLen - 1;
  1099.  
  1100.     if ( mStrLen < 16 ) {
  1101.         // Sample all the characters
  1102.          while ( curPos >= stop ) {
  1103.              hash = ( hash * 37 ) + *curPos; 
  1104.              curPos--;
  1105.          } }
  1106.      else {
  1107.          // only sample some characters
  1108.          int skip = mStrLen / 7;
  1109.          while ( curPos >= stop ) {
  1110.              hash = ( hash * 39 ) + *curPos;
  1111.              curPos -= skip;
  1112.          }
  1113.      }
  1114.      
  1115.      return hash;
  1116. }
  1117.  
  1118.  
  1119.  
  1120. bool UtilStr::Equals( const Hashable* inComp ) const {
  1121.     
  1122.     return compareTo( (UtilStr*) inComp ) == 0;
  1123. }
  1124.  
  1125.  
  1126.  
  1127.  
  1128.  
  1129. void UtilStr::AppendHex( char inB1, char inB2 ) {
  1130.     unsigned char c;
  1131.     
  1132.     if ( inB1 >= '0' && inB1 <= '9' )
  1133.         inB1 -= '0';
  1134.     else
  1135.         inB1 = 9 + inB1 & 0xF;
  1136.     c = inB1 << 4;
  1137.     
  1138.     if ( inB2 >= '0' && inB2 <= '9' )
  1139.         c += (inB2 - '0');
  1140.     else
  1141.         c += 9 + inB2 & 0xF;
  1142.     
  1143.  
  1144.     Append( (char) c );    
  1145. }
  1146.  
  1147.  
  1148. /*
  1149.  
  1150.  
  1151.  
  1152. long UtilStr::Hash( const char* inStr, long inStrLen ) {
  1153.     long hash = 0;
  1154.     const char* curPos = inStr + inStrLen - 1;
  1155.     
  1156.     if ( inStrLen < 0 )
  1157.         inStrLen = inStr's len
  1158.         
  1159.     if ( inStrLen < 16 ) {
  1160.         // Sample all the characters
  1161.          while ( curPos >= inStr ) {
  1162.              hash = ( hash * 37 ) + *curPos; 
  1163.              curPos--;
  1164.          } }
  1165.      else {
  1166.          // only sample some characters
  1167.          int skip = inStrLen / 7;
  1168.          while ( curPos >= inStr ) {
  1169.              hash = ( hash * 39 ) + *curPos;
  1170.              curPos -= skip;
  1171.          }
  1172.      }
  1173.      
  1174.      return hash;
  1175. }(*/
  1176.  
  1177.  
  1178.  
  1179.  
  1180.